package com.gok.model;

import lombok.*;

import javax.persistence.*;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@MappedSuperclass
@Data
@NoArgsConstructor  
@AllArgsConstructor
public abstract class BaseModel extends ReadOnlyBaseModel {
    private static final long serialVersionUID = -2823213714105834640l;
    @Column(nullable = false)
    protected Date updated;

    @Column(nullable = true)
    protected Date deleted;

    @Version
    @Column(nullable = false)
    protected Integer version = 0;

    @PrePersist
    protected void onCreate() {
        super.onCreate();
        updated = new Date();
    }

    @PreUpdate
    protected void onUpdate() {
        updated = new Date();
    }

    @Getter(AccessLevel.NONE)
    @Setter(AccessLevel.NONE)
    @Transient
    ThreadLocal<Map<String, String>> fieldUpdateBuffer;

    public void startNativeUpdate() {
        fieldUpdateBuffer.set(new HashMap<String, String>());
    }

    public void addFieldForUpdate(String fieldNameInTable, String valueInSql) {
        fieldUpdateBuffer.get().put(fieldNameInTable, valueInSql);
    }

    public String generateNativeUpdateSql() {
        if (fieldUpdateBuffer.get() == null) {
            throw new RuntimeException("No fields set for update");
        }

        StringBuilder sb = new StringBuilder();
        sb.append("UPDATE ").append(tableName()).append(" SET ");

        for (Map.Entry<String, String> entry : fieldUpdateBuffer.get().entrySet()) {
            sb.append(entry.getKey()).append(" = ").append(entry.getValue()).append(", ");
        }
        sb.append(", version = version + 1, updated = NOW() WHERE id = ").append(getId());

        fieldUpdateBuffer.remove();
        return sb.toString();
    }

    public String tableName() {
        return getClass().getAnnotation(Table.class).name();
    }
}

